package tableIdent;
import grammaire.YakaConstants;
import grammaire.YakaTokenManager;
import java.util.HashMap;
import java.util.Stack;

import controleurType.Constantes;


/**
 * Table permettant de stocker les identifiants reconnus dans le code
 * On se sert d'une hashmap dont les clés sont les noms des identifiants(String)
 * et le contenu est un objet Ident contenant les informations des identifiants
 * TEST:OK
 */
public class TabIdent implements YakaConstants{
	public HashMap<String,Ident> table;
	private static final int taille=1000;
	public Ident identCourant;
	public String identCourantNom;
	public Stack<String> pileDesVariables;
	public int typeCourant;
	public int offset;
	
	/**
	 * Constructeur par d�faut
	 * Cr�� la table des Identificateurs
	 * Initialise l'offset � 0
	 */
	public TabIdent() {
		table = new HashMap<String, Ident>(taille);
		offset=0;
		pileDesVariables= new Stack<String>();
	}	
	
	/**
	 * Teste la pr�sence d'un ident dans la table des Identificateurs
	 * @param key le nom � recherche
	 * @return Vrai s'il est pr�sent, Faux sinon
	 */
	public boolean existeIdent(String key){
		return table.containsKey(key);		
	}
	
	/**
	 * Cherche un Ident dans la table des Indentificateurs
	 * @param key le nom � rechercher
	 * @return L'Ident s'il est pr�sent
	 * @throws IdentifiantNonPresentException si l'identifiant n'est pas pr�sent
	 */
	public Ident chercheIdent(String key) throws IdentifiantNonPresentException{
		if(!existeIdent(key))	throw new IdentifiantNonPresentException("chercheIdent"+"identifiant: "+key);
		return table.get(key);
	}
	
	/**
	 * Ajoute un Ident dans la table des identificateurs
	 * Si l'ident est dans la table l'ancienne valeur est écrasée
	 * @param key L'identifiant auquel ajouter l'Ident
	 * @param id L'Ident � ajouter
	 */
	public void rangeIdent(String key, Ident id){
		table.put(key, id);
		if (id instanceof IdVar)//S'il s'agit d'une variable...
			offset+=2;//...on incr�mente l'offset de 2 (qu'il s'agisse d'un bool�en comme d'un entier)
	}
	
	/**
	 * Renvoie la HashMap sous forme textuelle (utilise la fonction par d�faut de HashMap)
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		return table.entrySet().toString();
	}

	/**
	 * Sauve l'identifiant de la Constante 
	 */
	public void sauveConstanteIdent(){
		identCourantNom = YakaTokenManager.identLu;
	}
		
	public void creerConstanteEntier(){
		identCourant = new IdConst(Constantes.ENTIERTYPE, YakaTokenManager.entierLu);
	}
	
	/**
	 * Cr�� l'Ident constante � partir d'un autre constante
	 * Recherche cette autre constante dans la table des Identificateurs
	 * @throws IdentifiantNonPresentException Si la constante "� droite" n'existe pas dans la table
	 */
	public void creerConstanteIdent() throws IdentifiantNonPresentException{
		Ident result = chercheIdent(YakaTokenManager.identLu);
		identCourant = result;
	}
	
	public void creerConstanteVrai(){
		identCourant = new IdConst(Constantes.BOOLEENTYPE, VRAI);
	}
	
	public void creerConstanteFaux(){
		identCourant = new IdConst(Constantes.BOOLEENTYPE, FAUX);
	}
	
	/**
	 * Ajoute dans la table des Identificateurs une Constante
	 */
	public void rangeConstante(){
		rangeIdent(identCourantNom, identCourant);		
	}
	
	
	/**
	 * Empile l'identifiant d'une variable
	 */
	public void empileVariableIdent(){
		pileDesVariables.push(YakaTokenManager.identLu);
	}
	
	/**
	 * Ajoute de multiples variables d'un m�me type dans la table des Identificateurs
	 */
	public void rangeVariables(){
		while(!pileDesVariables.isEmpty())
			rangeIdent(pileDesVariables.pop(),//On a plac� au pr�alable les identifiants dans la pile (via empileVarIdent())
					(new IdVar(typeCourant, offset)));//Les Ident sont des IdVar, on leur attribue l'offset courant (incr�ment� dans rangeIdent())
	}
	
		
}//class
